__author__ = 'Shir'

import pygame
import time
import thread
from pygame.locals import *

import os
import sys
import idlelib.PyShell
import paths

class UserScript(object):
    """Object for each user scripts.
    All will be saved in same directory defined in ..\paths.py
    directory must already exist!"""

    def __init__(self, control, script_dir = paths.FILE_SCRIPT_DIR, script_name = "testScript.py"):
        self.control = control
        self._name = script_name
        self._script_dir = script_dir
        self._full_path = os.path.join(sys.path[0], self._script_dir, self._name)

        # Make the press_key function available to the user, who is unaware of the UserScript class
        global press_key
        press_key = self.press_key
        time.sleep = self.framesleep

    def open_script_for_user_edit(self):

        backup_args = sys.argv
        sys.argv = []
        sys.argv.append(backup_args[0])
        sys.argv.append(self._full_path)
        idlelib.PyShell.main() # Causes invalid command name "218336992callit" error for some reason...
        sys.argv = backup_args

    def run_script(self):
        self.run_player_code()


    def check_code(self):
        pass

    def run_player_code(self):
        # Get current frame for timing purposes
        self.frame_to_run = self.control.current_frame # This variable follows all sleeps, etc. to know when to play different keys
        self.check_code()
        thread.start_new_thread(self._run_code_on_thread, ())

    def _run_code_on_thread(self):
        """Runs the player code on a separate thread with its own functions, as well as asynchronous timing.
        Need separate thread so player can write long-running code (time.sleep, etc.) but the game will still run normally"""
        lines = open(self._full_path, "r").readlines()
        for line in lines:
            exec(line, globals(), locals())

    def press_key(self, keycode, length=0.5):
        """The function run when the player wants a key to be pressed"""
        # Calculate times to run each press
        start_frame = self.frame_to_run
        end_frame = self.frame_to_run + length * self.control.fps
        # playback variable can be used to differentiate actual user keys and code.
        # For example, if we want to freeze user input during running of code
        pygame.event.post(pygame.event.Event(pygame.KEYDOWN, key=keycode, playback=True, frame_to_run = start_frame))
        pygame.event.post(pygame.event.Event(pygame.KEYUP, key=keycode, playback=True, frame_to_run = end_frame))

    def framesleep(self, seconds):
        """Imitates time.sleep, but instead of working on seconds, works on game frames.
        Allows user scripts to behave identically across different platforms"""
        self.frame_to_run += seconds * self.control.fps

def make_script_and_run(script_name):
    script = UserScript(paths.FILE_SCRIPT_DIR, script_name)
    userscript.open_script_for_user_edit()
    userscript.run_script()


def run_script_key_pressed(curr_userscript):
    try:
        curr_userscript.run_script()
    except Exception, e:
        print e
        raw_input()


def edit_script_key_pressed(curr_userscript):
    curr_userscript.open_script_for_user_edit()
